using System.Linq;
using FireStarter.Base;
using FireStarter.Base.BusinessObjectMerger;
using FireStarterModeller.BO;
using FireStarterModeller.Logic.MergeBusinessObjects;
using FireStarterModeller.Test.BO;
using Habanero.Testability;
using NUnit.Framework;

namespace FireStarterModeller.Test.Logic.MergeBusinessObjects
{
    [TestFixture]
    public class TestMergeUITab
    {
        [TestFixtureSetUp]
        public virtual void TestFixtureSetup()
        {
            TestUtilsLogic.SetupFixture();
        }
        [SetUp]
        public virtual void SetupTest()
        {
            TestUtilsLogic.SetupTest();
        }

        [Test]
        public void Test_MergeUITab_ShouldMergeUIColumnLayouts()
        {
            //---------------Set up test pack-------------------
            var uiColumnLayoutMerger = MergeableBORegistry.Instance.Resolve<UITab>();
            var fromUITab = TestUtilsUITab.GetFactory()
                .WithMany(columnLayout => columnLayout.UIColumnLayouts)
                .WithOutSingleRelationships()
                .CreateValidBusinessObject();
            var uiColumnLayouts = fromUITab.UIColumnLayouts;
            SetOrdinalPos(uiColumnLayouts[0]);
            SetOrdinalPos(uiColumnLayouts[1]);
            SetOrdinalPos(uiColumnLayouts[2]);
            var toUITab = new UITab();
            //---------------Assert Precondition----------------
            Assert.Greater(fromUITab.UIColumnLayouts.Count, 2);
            Assert.AreEqual(0, toUITab.UIColumnLayouts.Count);
            //---------------Execute Test ----------------------
            uiColumnLayoutMerger.MergeBOFrom(fromUITab, toUITab);
            //---------------Test Result -----------------------
            Assert.AreEqual(fromUITab.UIColumnLayouts.Count, toUITab.UIColumnLayouts.Count);
        }


        [Test]
        public void Test_MergeUITab_WhenTwoUpdatedFields_ShouldUpdateFields()
        {
            //---------------Set up test pack-------------------
            var uiColumnLayoutMerger = MergeableBORegistry.Instance.Resolve<UITab>();
            var fromUITab = TestUtilsUITab.GetFactory()
                .WithTwo(columnLayout => columnLayout.UIColumnLayouts)
                .WithOutSingleRelationships()
                .CreateValidBusinessObject();
            var uiColumnLayouts = fromUITab.UIColumnLayouts;
            var fromUIColumnLayout = uiColumnLayouts[0];
            SetOrdinalPos(fromUIColumnLayout);
            var fromUIColumnLayout2 = uiColumnLayouts[1];
            SetOrdinalPos(fromUIColumnLayout2);

            var toUITab = new UITab {Name = fromUITab.Name};
            UIColumnLayout expectedToUIColumnLayout = AddCopiedUIColumnLayout(toUITab, fromUIColumnLayout);
            UIColumnLayout expectedToUIColumnLayout2 = AddCopiedUIColumnLayout(toUITab, fromUIColumnLayout2);

            //---------------Assert Precondition----------------
            Assert.AreEqual(2, fromUITab.UIColumnLayouts.Count);
            Assert.AreEqual(fromUIColumnLayout.OrdinalPosition, expectedToUIColumnLayout.OrdinalPosition);
            Assert.AreEqual(fromUIColumnLayout.ToString(), expectedToUIColumnLayout.ToString());
            Assert.AreNotEqual(fromUIColumnLayout.Width, expectedToUIColumnLayout.Width);
            Assert.AreEqual(fromUIColumnLayout2.OrdinalPosition, expectedToUIColumnLayout2.OrdinalPosition);
            Assert.AreNotEqual(fromUIColumnLayout2.Width, expectedToUIColumnLayout2.Width);
            Assert.AreEqual(fromUIColumnLayout2.ToString(), expectedToUIColumnLayout2.ToString());
            //---------------Execute Test ----------------------
            uiColumnLayoutMerger.MergeBOFrom(fromUITab, toUITab);
            //---------------Test Result -----------------------
            Assert.IsNotNull(toUITab);
            Assert.AreEqual(2, toUITab.UIColumnLayouts.Count);
            var toUIColumnLayout = toUITab.UIColumnLayouts.First();
            Assert.AreEqual(fromUIColumnLayout.OrdinalPosition, toUIColumnLayout.OrdinalPosition);
            Assert.AreEqual(fromUIColumnLayout.Width, toUIColumnLayout.Width);
            var toUIColumnLayout2 = toUITab.UIColumnLayouts.Last();
            Assert.AreEqual(fromUIColumnLayout2.OrdinalPosition, toUIColumnLayout2.OrdinalPosition);
            Assert.AreEqual(fromUIColumnLayout2.Width, toUIColumnLayout2.Width);
        }

        private static void SetOrdinalPos(UIColumnLayout uiColumnLayout)
        {
            uiColumnLayout.OrdinalPosition = GetValidOrdinalPos(uiColumnLayout);
        }

        private static int? GetValidOrdinalPos(UIColumnLayout uiColumnLayout)
        {
            return GetFactory().GetValidPropValue(uiColumnLayout, layout => layout.OrdinalPosition);
        }

        private static BOTestFactory<UIColumnLayout> GetFactory()
        {
            return TestUtilsUIColumnLayout.GetFactory();
        }


        [Test]
        public void Test_MergeUITab_WhenOneRemovedUiField_ShouldUpdateFieldStatusToDelete()
        {
            //---------------Set up test pack-------------------
            var uiColumnLayoutMerger = MergeableBORegistry.Instance.Resolve<UITab>();
            var fromUITab = new UITab();
            var fromUIColumnLayout = CreateUIColumnLayout(fromUITab);
            var fromUIColumnLayout2 = CreateUIColumnLayout(fromUITab);
            var toUITab = new UITab();
            UIColumnLayout expectedToUIColumnLayout = AddCopiedUIColumnLayout(toUITab, fromUIColumnLayout);
            UIColumnLayout expectedToUIColumnLayout2 = AddCopiedUIColumnLayout(toUITab, fromUIColumnLayout2);
            fromUITab.UIColumnLayouts.Remove(fromUIColumnLayout2);
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, fromUITab.UIColumnLayouts.Count);
            Assert.AreEqual(2, toUITab.UIColumnLayouts.Count);
            Assert.AreNotEqual(fromUIColumnLayout.Width, expectedToUIColumnLayout.Width);
            Assert.AreNotEqual(ChangeType.Update, expectedToUIColumnLayout.PendingChangeType);
            Assert.AreNotEqual(ChangeType.Delete, expectedToUIColumnLayout2.PendingChangeType);
            //---------------Execute Test ----------------------
            uiColumnLayoutMerger.MergeBOFrom(fromUITab, toUITab);
            //---------------Test Result -----------------------

            Assert.IsNotNull(toUITab);
            Assert.AreEqual(2, toUITab.UIColumnLayouts.Count);
            var toUIColumnLayout = toUITab.UIColumnLayouts.First();
            Assert.AreSame(toUIColumnLayout, expectedToUIColumnLayout);

            var toUIColumnLayout2 = toUITab.UIColumnLayouts.Last();
            Assert.AreSame(toUIColumnLayout2, expectedToUIColumnLayout2);
            Assert.AreEqual(ChangeType.Delete, toUIColumnLayout2.PendingChangeType);
            Assert.AreEqual(ChangeType.None, toUIColumnLayout.PendingChangeType);
        }

        [Test]
        public void Test_MergeUITab_WhenMergeToNotNull_ShouldUpdateUITab()
        {
            //---------------Set up test pack-------------------
            IMergeBO<UITab> mergeBO = MergeableBORegistry.Instance.Resolve<UITab>();
            var boTestFactory = TestUtilsUITab.GetFactory();
            var fromUITab = boTestFactory
                .WithMany(columnLayout => columnLayout.UIColumnLayouts)
                .WithOutSingleRelationships()
                .CreateValidBusinessObject();
            var toUiField = new UITab();
            //---------------Assert Precondition----------------
            Assert.AreNotEqual(fromUITab.Name, toUiField.Name);
            //---------------Execute Test ----------------------
            mergeBO.MergeBOFrom(fromUITab, toUiField);
            //---------------Test Result -----------------------
            Assert.AreEqual(fromUITab.Name, toUiField.Name);
        }

        private static UIColumnLayout AddCopiedUIColumnLayout(UITab toUITab, UIColumnLayout fromUIfield)
        {
            var expectedToUIField = new UIColumnLayout { OrdinalPosition = fromUIfield.OrdinalPosition };
            expectedToUIField.Width = RandomValueGen.GetRandomInt();
            toUITab.UIColumnLayouts.Add(expectedToUIField);
            return expectedToUIField;
        }

        private static UIColumnLayout CreateUIColumnLayout(UITab uiTab)
        {
            var uiColumnLayout = uiTab.UIColumnLayouts.CreateBusinessObject();
            uiColumnLayout.Width = GetFactory().GetValidPropValue(layout => layout.Width);
            uiColumnLayout.OrdinalPosition = GetFactory().GetValidPropValue(layout => layout.OrdinalPosition);
            return uiColumnLayout;
        }
    }
}